using System;
using System.Collections;
using System.IO;
using System.Threading;
using Core;
using Core.Extensions;


namespace SolarDevices
{
    public class EventLogger
    {
        private static EventLogger _singleton;
        private readonly string _location;

        private EventLogger(string dayEvents)
        {
            _location = dayEvents;
        }

        public string DayEvents
        {
            get
            {
                return _location + "\\day.txt";
            }
        }

        public string History
        {
            get
            {
                return _location + "\\history.txt";
            }
        }

        public static EventLogger GetLogger(string location = "")
        {
            if (_singleton == null && (location == null || location.Equals("")))
            {
                throw new ArgumentNullException("must provide logfile");
            }
            return _singleton ?? (_singleton = new EventLogger(location));
        }

        public void Log(string msg)
        {
            lock (this)
            {
                var d = DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss");
                using (var s = new FileStream(DayEvents, FileMode.Append, FileAccess.Write))
                {
                    using (var w = new StreamWriter(s))
                    {
                        w.WriteLine(string.Concat(d, " ", msg));
                        w.Close();
                    }
                    s.Close();
                }
            }
        }

        public void LogDayEvent(ChargeEvent ce)
        {
            lock (this)
            {
                if (!File.Exists(DayEvents))
                {
                    var s1 = File.Create(DayEvents);
                    s1.Close();
                }
                var d = DateTime.Now.Ticks.ToString();
                using (var s = new FileStream(DayEvents, FileMode.Append, FileAccess.Write))
                {
                    using (var w = new StreamWriter(s))
                    {
                        var sb = new StringBuilder(d);
                        sb.Append(", ");
                        sb.Append(ce.StateCode.ToString());
                        sb.Append(", ");
                        sb.Append(ce.Generator? "1" : "0");
                        w.WriteLine(sb.ToString());
                        w.Close();
                    }
                    s.Close();
                }
            }
        }

        private bool IsComplete
        {
            get
            {
                if (!File.Exists(DayEvents))
                    return false;
                var fi = new FileInfo(DayEvents);
                return fi.Length > 500;
            }
        }
        public void ClearDayEvents()
        {
            if (!File.Exists(DayEvents))
                return;
            lock (this)
            {
                File.Delete(DayEvents);
            }
        }

        internal void CreateSummary(ChargeEvent ce)
        {
            if (IsComplete)
            {
                lock (this)
                {
                    bool generator = false;
                    int maxState = 0;
                    var today = DateTime.Today;
                    using (var s = new FileStream(DayEvents, FileMode.Open, FileAccess.Read))
                    {
                        using (var r = new StreamReader(s))
                        {
                            string rec;
                            while (!(rec = r.ReadLine()).IsNullOrEmpty())
                            {
                                string[] values = rec.Split(new[] { ',' }, 3);
                                var date = new DateTime(long.Parse(values[0]));
                                if (date >= today)
                                {
                                    var sc = int.Parse(values[1]);
                                    maxState = Math.Max(maxState, sc);
                                    var g = int.Parse(values[2]);
                                    if (g != 0) generator = true;
                                }
                            }
                            r.Close();
                        }
                        s.Close();
                    }
                    if (!File.Exists(History))
                    {
                        var s1 = File.Create(History);
                        s1.Close();
                    }
                    Thread.Sleep(5);
                    using (var s = new FileStream(History, FileMode.Append, FileAccess.Write))
                    {
                        using (var w = new StreamWriter(s))
                        {
                            var d = DateTime.Now;
                            var sb = new StringBuilder(d.Date.Ticks.ToString());
                            sb.Append(", ");
                            sb.Append(ce.EnergyToday);
                            sb.Append(", ");
                            sb.Append(maxState.ToString());
                            sb.Append(", ");
                            sb.Append(generator ? "1" : "0");
                            w.WriteLine(sb.ToString());
                            w.Close();
                        }
                        s.Close();
                    }

                }
                Thread.Sleep(5);
                ClearDayEvents();
            }
        }

        public object[] GetEvents(DateTime startDt, DateTime endDt)
        {
            var al = new ArrayList();
            if (File.Exists(History))
            {
                lock (this)
                {
                    try
                    {
                        using (var s = new FileStream(History, FileMode.Open, FileAccess.Read))
                        {
                            using (var r = new StreamReader(s))
                            {
                                string rec;
                                while (!(rec = r.ReadLine()).IsNullOrEmpty())
                                {
                                    var values = rec.Split(new[] {','}, 4);
                                    var max = DateTime.MaxValue;
                                    var min = DateTime.MinValue;
                                    var date = new DateTime(long.Parse(values[0]));
                                    if (date >= startDt && date <= endDt)
                                    {
                                        var kwh = double.Parse(values[1]);
                                        var sc = int.Parse(values[2]);
                                        var generator = int.Parse(values[3]);
                                        var sb = new StringBuilder();
                                        sb.Append(kwh.ToString("f1"));
                                        sb.Append(" kWh ");
                                        al.Add(new EventObject { start = date.ToString("yyyy-MM-dd"), title = sb.ToString() });
                                        sb = new StringBuilder();
                                        switch (sc)
                                        {
                                            case 3:
                                                sb.Append(" (Float)");
                                                break;
                                            case 4:
                                                sb.Append(" (Equalize)");
                                                break;
                                        }
                                        if (generator != 0)
                                        {
                                            sb.Append(" (Generator)");
                                        }
                                        if (sb.Length > 0)
                                        {
                                            al.Add(new EventObject { start = date.ToString("yyyy-MM-dd"), title = sb.ToString() });
                                        }
                                    }
                                }
                                r.Close();
                            }
                            s.Close();
                        }
                    }
                    catch (Exception ex)
                    {
                        DebugLogger.TryLog(ex);
                    }

                }
            }
            return al.ToArray();
        }
    }
}
